#include "unistd.h"

#include "ijkplayer.h"
#include "ijkplayer_internal.h"


#include "pipeline/ffpipeline_ffplay.h"
#include "pipeline/ffpipenode_ffplay_vdec.h"
#include "linux/ijksdl_vout_SDL_surface.h"

#include "util/dump_pts.h"

static int refresh_loop_wait_event(SDL_Event *event) {
    SDL_PumpEvents();
    return  SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
}

static void do_exit(IjkMediaPlayer *mp)
{
    MPTRACE("do_exit\n");
    ijkmp_stop(mp);
    ijkmp_dec_ref_p(&mp);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
static void message_event_n(IjkMediaPlayer *mp)
{
    SDL_Event event;
    long incr, current_position;
    event.type = 0;
    while (refresh_loop_wait_event(&event)) {
        switch (event.type) {
            case SDL_KEYDOWN:
                switch (event.key.keysym.sym) {
                    case SDLK_ESCAPE:
                    case SDLK_q:
                        do_exit(mp);
                        break;
//                    case SDLK_f:
//                        toggle_full_screen(cur_stream);
//                        cur_stream->force_refresh = 1;
//                        break;
                    case SDLK_p:
                        ijkmp_start(mp);
                        break;
                    case SDLK_SPACE:
                        ijkmp_pause(mp);
                        break;
                    case SDLK_LEFT:
                        incr = -10 * 1000;
                        goto do_seek;
                    case SDLK_RIGHT:
                        incr = 10 * 1000;
                        goto do_seek;
                    case SDLK_UP:
                        incr = 60 * 1000;
                        goto do_seek;
                    case SDLK_DOWN:
                        incr = -60 * 1000;
                    do_seek:
                        current_position = ijkmp_get_current_position(mp) + incr;
                        ijkmp_seek_to(mp, current_position);
//                        pos = get_master_clock(cur_stream);
//                        if (isnan(pos))
//                            pos = (double)cur_stream->seek_pos / AV_TIME_BASE;
//                        pos += incr;
//                        if (cur_stream->ic->start_time != AV_NOPTS_VALUE && pos < cur_stream->ic->start_time / (double)AV_TIME_BASE)
//                            pos = cur_stream->ic->start_time / (double)AV_TIME_BASE;
//                        stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE), 0);

                        break;
                    default:
                        break;
                }
            case SDL_WINDOWEVENT:
                switch (event.window.event) {
                    case SDL_WINDOWEVENT_RESIZED:
                        SDL_VoutSetScreenSize(mp->ffplayer->vout, event.window.data1, event.window.data2);
                        break;
                    case SDL_WINDOWEVENT_EXPOSED:
                        break;
                }
                break;
            case SDL_MOUSEMOTION:
                //SDL_ShowCursor(1);
                break;
//        case SDL_QUIT:
//            break;
            default:
                break;
        }
    }

}

static void message_loop_n(IjkMediaPlayer *mp)
{
    while (1) {
        AVMessage msg;

        int retval = ijkmp_get_msg(mp, &msg, 1);
        if (retval < 0)
            break;

        if (retval == 0) {
            message_event_n(mp);
            continue;
        }

        // block-get should never return 0
        assert(retval > 0);

        switch (msg.what) {
            case FFP_MSG_FLUSH:
                MPTRACE("FFP_MSG_FLUSH:\n");
                //post_event(env, weak_thiz, MEDIA_NOP, 0, 0);
                break;
            case FFP_MSG_ERROR:
                MPTRACE("FFP_MSG_ERROR: %d\n", msg.arg1);
                //post_event(env, weak_thiz, MEDIA_ERROR, MEDIA_ERROR_IJK_PLAYER, msg.arg1);
                break;
            case FFP_MSG_PREPARED:
                MPTRACE("FFP_MSG_PREPARED:\n");
                //post_event(env, weak_thiz, MEDIA_PREPARED, 0, 0);
                break;
            case FFP_MSG_COMPLETED:
                MPTRACE("FFP_MSG_COMPLETED:\n");
                //post_event(env, weak_thiz, MEDIA_PLAYBACK_COMPLETE, 0, 0);
                break;
            case FFP_MSG_VIDEO_SIZE_CHANGED:
                MPTRACE("FFP_MSG_VIDEO_SIZE_CHANGED: %d, %d\n", msg.arg1, msg.arg2);
                //post_event(env, weak_thiz, MEDIA_SET_VIDEO_SIZE, msg.arg1, msg.arg2);
                break;
            case FFP_MSG_SAR_CHANGED:
                MPTRACE("FFP_MSG_SAR_CHANGED: %d, %d\n", msg.arg1, msg.arg2);
                //post_event(env, weak_thiz, MEDIA_SET_VIDEO_SAR, msg.arg1, msg.arg2);
                break;
            case FFP_MSG_VIDEO_RENDERING_START:
                MPTRACE("FFP_MSG_VIDEO_RENDERING_START:\n");
                //post_event(env, weak_thiz, MEDIA_INFO, MEDIA_INFO_VIDEO_RENDERING_START, 0);
                break;
            case FFP_MSG_AUDIO_RENDERING_START:
                MPTRACE("FFP_MSG_AUDIO_RENDERING_START:\n");
                //post_event(env, weak_thiz, MEDIA_INFO, MEDIA_INFO_AUDIO_RENDERING_START, 0);
                break;
            case FFP_MSG_VIDEO_ROTATION_CHANGED:
                MPTRACE("FFP_MSG_VIDEO_ROTATION_CHANGED: %d\n", msg.arg1);
                //post_event(env, weak_thiz, MEDIA_INFO, MEDIA_INFO_VIDEO_ROTATION_CHANGED, msg.arg1);
                break;
            case FFP_MSG_AUDIO_DECODED_START:
                MPTRACE("FFP_MSG_AUDIO_DECODED_START:\n");
                //post_event(env, weak_thiz, MEDIA_INFO, MEDIA_INFO_AUDIO_DECODED_START, 0);
                break;
            case FFP_MSG_VIDEO_DECODED_START:
                MPTRACE("FFP_MSG_VIDEO_DECODED_START:\n");
                //post_event(env, weak_thiz, MEDIA_INFO, MEDIA_INFO_VIDEO_DECODED_START, 0);
                break;
            case FFP_MSG_OPEN_INPUT:
                MPTRACE("FFP_MSG_OPEN_INPUT:\n");
                //post_event(env, weak_thiz, MEDIA_INFO, MEDIA_INFO_OPEN_INPUT, 0);
                break;
            case FFP_MSG_FIND_STREAM_INFO:
                MPTRACE("FFP_MSG_FIND_STREAM_INFO:\n");
                //post_event(env, weak_thiz, MEDIA_INFO, MEDIA_INFO_FIND_STREAM_INFO, 0);
                break;
            case FFP_MSG_COMPONENT_OPEN:
                MPTRACE("FFP_MSG_COMPONENT_OPEN:\n");
                //post_event(env, weak_thiz, MEDIA_INFO, MEDIA_INFO_COMPONENT_OPEN, 0);
                break;
            case FFP_MSG_BUFFERING_START:
                MPTRACE("FFP_MSG_BUFFERING_START:\n");
                //post_event(env, weak_thiz, MEDIA_INFO, MEDIA_INFO_BUFFERING_START, msg.arg1);
                break;
            case FFP_MSG_BUFFERING_END:
                MPTRACE("FFP_MSG_BUFFERING_END:\n");
                //post_event(env, weak_thiz, MEDIA_INFO, MEDIA_INFO_BUFFERING_END, msg.arg1);
                break;
            case FFP_MSG_BUFFERING_UPDATE:
                MPTRACE("FFP_MSG_BUFFERING_UPDATE: %d, %d", msg.arg1, msg.arg2);
                //post_event(env, weak_thiz, MEDIA_BUFFERING_UPDATE, msg.arg1, msg.arg2);
                break;
            case FFP_MSG_BUFFERING_BYTES_UPDATE:
                break;
            case FFP_MSG_BUFFERING_TIME_UPDATE:
                break;
            case FFP_MSG_SEEK_COMPLETE:
                MPTRACE("FFP_MSG_SEEK_COMPLETE:\n");
                //post_event(env, weak_thiz, MEDIA_SEEK_COMPLETE, 0, 0);
                break;
            case FFP_MSG_ACCURATE_SEEK_COMPLETE:
                MPTRACE("FFP_MSG_ACCURATE_SEEK_COMPLETE:\n");
                //post_event(env, weak_thiz, MEDIA_INFO, MEDIA_INFO_MEDIA_ACCURATE_SEEK_COMPLETE, msg.arg1);
                break;
            case FFP_MSG_PLAYBACK_STATE_CHANGED:
                break;
            case FFP_MSG_TIMED_TEXT:
                if (msg.obj) {
                    MPTRACE("FFP_MSG_TIMED_TEXT:%s\n", (char *)msg.obj);
//                    jstring text = (*env)->NewStringUTF(env, (char *)msg.obj);
//                    post_event2(env, weak_thiz, MEDIA_TIMED_TEXT, 0, 0, text);
//                    J4A_DeleteLocalRef__p(env, &text);
                }
                else {
                    MPTRACE("FFP_MSG_TIMED_TEXT:\n");
                    //post_event2(env, weak_thiz, MEDIA_TIMED_TEXT, 0, 0, NULL);
                }
                break;
            case FFP_MSG_GET_IMG_STATE:
                MPTRACE("FFP_MSG_GET_IMG_STATE:\n");
                if (msg.obj) {
                      MPTRACE("FFP_MSG_GET_IMG_STATE:%s\n", (char *)msg.obj);
//                    jstring file_name = (*env)->NewStringUTF(env, (char *)msg.obj);
//                    post_event2(env, weak_thiz, MEDIA_GET_IMG_STATE, msg.arg1, msg.arg2, file_name);
//                    J4A_DeleteLocalRef__p(env, &file_name);
                }
                else {
                        MPTRACE("FFP_MSG_GET_IMG_STATE:\n");
//                    post_event2(env, weak_thiz, MEDIA_GET_IMG_STATE, msg.arg1, msg.arg2, NULL);
                }
                break;
            case FFP_MSG_VIDEO_SEEK_RENDERING_START:
                MPTRACE("FFP_MSG_VIDEO_SEEK_RENDERING_START:\n");
                //post_event(env, weak_thiz, MEDIA_INFO, MEDIA_INFO_VIDEO_SEEK_RENDERING_START, msg.arg1);
                break;
            case FFP_MSG_AUDIO_SEEK_RENDERING_START:
                MPTRACE("FFP_MSG_AUDIO_SEEK_RENDERING_START:\n");
                //post_event(env, weak_thiz, MEDIA_INFO, MEDIA_INFO_AUDIO_SEEK_RENDERING_START, msg.arg1);
                break;
            default:
                ALOGE("unknown FFP_MSG_xxx(%d)\n", msg.what);
                break;
        }
        msg_free_res(&msg);
    }

    LABEL_RETURN:
    ;
}

static int message_loop(void *arg)
{
    MPTRACE("%s\n", __func__);

    IjkMediaPlayer *mp = (IjkMediaPlayer*) arg;


    message_loop_n(mp);

    LABEL_RETURN:
    ijkmp_dec_ref_p(&mp);

    MPTRACE("message_loop exit");
    return 0;
}

int main(int argc, char **argv)
{
    int ret = -1;
    char *filename = NULL;

    if ((argc != 2))
    {
        MPTRACE("argc:%d not right\n", argc);
        MPTRACE("Input Format: \n");
        MPTRACE("ijkplayer file_name\n");
        return 0;
    }
    filename = argv[1];
    MPTRACE("filenme: %s\n", filename);

    dump_pts_init(1);

    ijkmp_global_init();

    ijkmp_global_set_log_report(1);
    ijkmp_global_set_log_level(AV_LOG_INFO);

    IjkMediaPlayer *mp = ijkmp_create(message_loop);
    if (!mp)
        goto fail;

    mp->ffplayer->vout = SDL_VoutAndroid_CreateForSDLSurface();
    if (!mp->ffplayer->vout)
        goto fail;


    IJKFF_Pipeline *pipeline = ffpipeline_create_from_ffplay(mp->ffplayer);
    mp->ffplayer->pipeline = pipeline;
    if (!mp->ffplayer->pipeline)
        goto fail;

    ret = ijkmp_set_data_source(mp, filename);
    MPTRACE("set source, ret:%d\n", ret);
    ret = ijkmp_prepare_async(mp);
    MPTRACE("prepare, ret:%d\n", ret);

    while (1) {
        int ijkstate = ijkmp_get_state(mp);
        if (ijkstate != MP_STATE_ASYNC_PREPARING)
            break;
    }
    ret = ijkmp_start(mp);
    MPTRACE("start, ret:%d\n", ret);


    long playable_duration = ijkmp_get_playable_duration(mp);
    MPTRACE("playable_duration:%ld\n", playable_duration);

    long duration = ijkmp_get_duration(mp);
    MPTRACE("duration:%ld\n", duration);


    long current_position = ijkmp_get_current_position(mp);
    MPTRACE("current_position:%ld\n", current_position);

    while (duration - current_position > 100 && (ijkmp_get_state(mp) == MP_STATE_PREPARED ||
                                                 ijkmp_get_state(mp) == MP_STATE_STARTED ||
                                                 ijkmp_get_state(mp) == MP_STATE_PAUSED))
    {
        current_position = ijkmp_get_current_position(mp);
        MPTRACE("layable_duration:%ld\n", current_position);
        usleep(1 * 1000 * 1000);
    }

    MPTRACE("finish\n");
    if (ijkmp_get_state(mp) != MP_STATE_IDLE)
    {
        ret = ijkmp_stop(mp);
    }
    ijkmp_dec_ref_p(&mp);

    //usleep( 100 * 1000);
    //SDL_Quit();
    dump_pts_close();
fail:
    return 0;
}
